using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Mvc;
using Localization;
using log4net;
using SinBiota.Model.Business.AuthenticationServices.Interfaces;
using SinBiota.Model.Exceptions;
using Sinbiota.Web.ActionFilters;
using Sinbiota.Web.Models;
using System.Linq;
using StructureMap;


namespace Sinbiota.Web.Controllers
{
    public abstract class BaseController : Controller
    {
        protected string SearchBoxName = "Search";
        private IPermissionServices _permissionServices;

        protected void SetInformationMessage(string message)
        {
            ViewData["InformationMessage"] = message;
        }

        protected void SetErrorMessage(string message)
        {
            ViewData["ErrorMessage"] = message;
        }
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            var log = LogManager.GetLogger(filterContext.Controller.GetType());
            GlobalContext.Properties["AuthenticatedUser"] = User.Identity.Name ?? "Anon";
            log.Info(string.Format("{0} - {1}", filterContext.ActionDescriptor.ActionName, filterContext.HttpContext.Request.RequestType));

            // Styles:
            ViewData["ActionButtonBase"] = "nice blue button round";
            ViewData["ActionButtonClass"] = ViewData["ActionButtonBase"] + " small";
        }

        [ExportMessagesToTempData]
        protected override void OnException(ExceptionContext exceptionContext)
        {
            var exception = exceptionContext.Exception;
            // Message:
            var message = new StringBuilder();

            while (exception != null)
            {
                message.Append(exception.Message).Append(". ");
                exception = exception.InnerException;
            }
            exception = exceptionContext.Exception;
            //LOG:
            var log = LogManager.GetLogger(exceptionContext.Controller.GetType());
            GlobalContext.Properties["AuthenticatedUser"] = User.Identity.Name ?? "Anon";
            log.Error(message.ToString(), exceptionContext.Exception);
            //Exception:
            exceptionContext.ExceptionHandled = true;
            if (exceptionContext.HttpContext.Request.IsAjaxRequest())
            {
                exceptionContext.Result = new JsonResult
                {
                    Data = JsonMessage.ErrorMessage(message.ToString(), exceptionContext.Exception.StackTrace)
                };
            }
            else
            {
                exceptionContext.ExceptionHandled = true;
                //exceptionContext.Controller.TempData["ErrorMessage"] = message.ToString();
                _permissionServices = ObjectFactory.GetInstance<IPermissionServices>();
                _permissionServices.IsAdmin(User.Identity.Name);
                var errorModel = new ErrorModel(exception, _permissionServices.IsAdmin(User.Identity.Name), message.ToString());
                if (exception.GetType().Equals(typeof(PersistenceException)))
                {
                    // TODO: could add more cases here if necessary:
                    if (message.ToString().Contains("DELETE statement conflicted with the REFERENCE constraint "))
                    {
                        errorModel.FriendlyMessage = Messages.DeleteConflictError;
                    }
                    else 
                    {
                        errorModel.FriendlyMessage = Messages.DatabaseErrorProcessingOperation;
                        
                    }
                }
                else if (exception.GetType().Equals(typeof(AuthorizationException)))
                {
                    errorModel.FriendlyMessage = Messages.CurrentUserDoesNotHavePermissionForThisOperation;
                }
                else
                {
                    errorModel.FriendlyMessage = Strings.UnexpectedError;
                }
                View("Error", errorModel).ExecuteResult(ControllerContext);
            }
        }

        protected string ValidationErrorMessage()
        {
            var s = new List<String> { "<ul>" };
            s.AddRange(ModelState.Where(x => x.Value.Errors.Count > 0)
                .Select(pair => String.Format("<b>{0}</b>: {1}", pair.Key, String.Join(", ", pair.Value.Errors.Select(x => x.ErrorMessage)))).Select(error => "<li>" + error + "</li>"));
            s.Add("</ul>");
            return String.Join("", s);
        }


    }
}